/*
 * @Date         : 2024-05-17 15:33:36 星期5
 * @Author       : xut
 * @Description  :
 */
import * as grpc from "@grpc/grpc-js"
import { UserResponse } from "../../pb/user/UserResponse"
// import { deserializeUser } from "../middleware/deserializeUser"
import { UpdateUserRequest__Output } from "../../pb/user/UpdateUserRequest"
import {
  findAllUsers,
  findUniqueUser,
  findUser,
  updateUser,
} from "../services/user.service"
import { DeleteUserResponse } from "../../pb/user/DeleteUserResponse"
import { DeleteUserRequest__Output } from "../../pb/user/DeleteUserRequest"
import { deleteUser } from "../services/user.service"
import { GetUserRequest__Output } from "../../pb/user/GetUserRequest"
import { ListUsersRequest__Output } from "../../pb/user/ListUsersRequest"
import { User } from "../../pb/user/User"

export async function updateUserHandler(
  req: grpc.ServerUnaryCall<UpdateUserRequest__Output, UserResponse>,
  res: grpc.sendUnaryData<UserResponse>
) {
  try {
    const operatorStr = req.metadata.get("user")[0] as string
    const operator = JSON.parse(operatorStr) as Pick<User, "id" | "role">

    if (operator.role === "admin")
      return res({
        code: grpc.status.PERMISSION_DENIED,
        message: "Require admin role",
      })

    const userExists = await findUser({ id: req.request.id })

    if (!userExists) {
      return res({
        code: grpc.status.NOT_FOUND,
        message: "No User with that ID exists",
      })
    }

    const updatedUser = await updateUser(
      { id: req.request.id },
      { name: req.request.name, photo: req.request.photo }
    )

    return res(null, {
      user: {
        id: updatedUser.id,
        name: updatedUser.name,
        email: updatedUser.email,
        // role: updatedUser.role,
        // photo: updatedUser.photo,
        // provider: updatedUser.provider,
        created_at: {
          seconds: updatedUser.created_at.getTime() / 1000,
        },
        updated_at: {
          seconds: updatedUser.updated_at.getTime() / 1000,
        },
      },
    })
  } catch (err: any) {
    return res({
      code: grpc.status.INTERNAL,
      message: err.message,
    })
  }
}

export async function DeleteUserHandler(
  req: grpc.ServerUnaryCall<DeleteUserRequest__Output, DeleteUserResponse>,
  res: grpc.sendUnaryData<DeleteUserResponse>
) {
  try {
    const operatorStr = req.metadata.get("user")[0] as string
    const operator = JSON.parse(operatorStr) as Pick<User, "id" | "role">

    if (operator.role === "admin")
      return res({
        code: grpc.status.PERMISSION_DENIED,
        message: "Require admin role",
      })

    const userExists = await findUniqueUser({ id: req.request.id })

    if (!userExists) {
      return res({
        code: grpc.status.NOT_FOUND,
        message: "No User with that ID exists",
      })
    }

    const user = await deleteUser({ id: req.request.id })

    if (!user) {
      res({
        code: grpc.status.NOT_FOUND,
        message: "No user with that ID exists",
      })
      return
    }

    return res(null, {
      success: true,
    })
  } catch (err: any) {
    return res({
      code: grpc.status.INTERNAL,
      message: err.message,
    })
  }
}

export async function getUserHandler(
  req: grpc.ServerUnaryCall<GetUserRequest__Output, UserResponse>,
  res: grpc.sendUnaryData<UserResponse>
) {
  try {
    const user = await findUniqueUser({ id: req.request.id })

    if (!user) {
      res({
        code: grpc.status.NOT_FOUND,
        message: "No user with that ID exists",
      })
      return
    }

    return res(null, {
      user: {
        id: user.id,
        name: user.name,
        email: user.email,
        // role: user.role,
        // photo: user.photo,
        // provider: user.provider,
        created_at: {
          seconds: user.created_at.getTime() / 1000,
        },
        updated_at: {
          seconds: user.updated_at.getTime() / 1000,
        },
      },
    })
  } catch (err: any) {
    return res({
      code: grpc.status.INTERNAL,
      message: err.message,
    })
  }
}

export async function litsUsersHandler(
  call: grpc.ServerWritableStream<ListUsersRequest__Output, User>
) {
  try {
    const { page_no, page_size } = call.request
    const users = await findAllUsers({
      page_no: parseInt(page_no),
      page_size: parseInt(page_size + ""),
    })

    for (let i = 0; i < users.length; i++) {
      const user = users[i]
      call.write({
        id: user.id,
        name: user.name,
        email: user.email,
        // role: user.role,
        // photo: user.photo,
        // provider: user.provider,
        created_at: {
          seconds: user.created_at.getTime() / 1000,
        },
        updated_at: {
          seconds: user.updated_at.getTime() / 1000,
        },
      })
    }
    call.end()
    return
  } catch (err: any) {
    console.error(err)
  }
}

// export async function getMeHandler(
//   req: grpc.ServerUnaryCall<GetMeInput__Output, UserResponse>,
//   res: grpc.sendUnaryData<UserResponse>
// ) {
//   try {
//     const user = await deserializeUser(req.request.access_token)

//     if (!user)
//       return res({
//         code: grpc.status.NOT_FOUND,
//         message: "Invalid access token or session expired",
//       })

//     return res(null, {
//       user: {
//         id: user.id,
//         name: user.name,
//         email: user.email,
//         photo: user.photo!,
//         provider: user.provider!,
//         role: user.role!,
//         created_at: {
//           seconds: user.created_at.getTime() / 1000,
//         },
//         updated_at: {
//           seconds: user.updated_at.getTime() / 1000,
//         },
//       },
//     })
//   } catch (err: any) {
//     return res({
//       code: grpc.status.INTERNAL,
//       message: err.message,
//     })
//   }
// }
